package com.youi.util;


import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.io.FileUtils;





public class CreateEntityUtil { 
	
	public static void main(String[] args) throws Exception {		
//		createEntityUtil("User","用户信息");
		createAllEntity();
	}
	
	
	
	private final static String packagePath="com.youi.entity";
	    
    private static String[] colnames; // 列名数组  
    
    private static String[] colcomment;  //注释数组
  
    private static String[] colTypes; // 列名类型数组  
  
    private static int[] colSizes; // 列名大小数组  
  
    private static boolean f_util = false; // 是否需要导入包java.util.*  
  
    private static boolean f_sql = false; // 是否需要导入包java.sql.* 
    
    private static boolean f_ser = true; // 是否需要导入包java.sql.* 
    
    private final static String MYSQLURL="jdbc:mysql://127.0.0.1:3306/meiyijiahealth?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true";
    
    private final static String NAME="root";
    
    private final static String PASSWORD="123456";
    
    private final static String DATASOURCE="meiyijiahealth";
    
    
    /**
     * 建立数据库所有的实体类
     * @param packagePath 存放路径
     */
    public static void createAllEntity() {
    	List<String> tableName=getAllTableNames();
		for (String name : tableName) {
			createEntityUtil(name,null);
		}
	}
    
    
    /**
     * 建立单个实体类
     * @param memo  备注
     * @param tableName	   表名
     */
    public static void createEntityUtil(String tableName,String memo) {       
        try {
        	Connection conn = DriverManager.getConnection(MYSQLURL,NAME,PASSWORD);
            PreparedStatement pstmt = null;
            String strsql = "select * from " + tableName;
            pstmt = conn.prepareStatement(strsql);
            ResultSetMetaData rsmd = pstmt.getMetaData();
            int size = rsmd.getColumnCount(); // 共有多少列
            colnames = new String[size];
            colTypes = new String[size];
            colSizes = new int[size];
            colcomment=getColumnCommentByTableName(tableName);
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
                colnames[i] = getCamelStr(rsmd.getColumnName(i + 1));                
                colTypes[i] = rsmd.getColumnTypeName(i + 1);
                if (colTypes[i].equalsIgnoreCase("datetime")) {
                    f_util = true;
                }
                if (colTypes[i].equalsIgnoreCase("image")
                        || colTypes[i].equalsIgnoreCase("text")) {
                    f_sql = true;
                }
                colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
            }
            try {
            	String content = parse(colnames, colTypes, colSizes, packagePath, tableName,memo);
            	//普通工程存放路径
//            	String path = System.getProperty("user.dir") + "/src/" + packagePath.replaceAll("\\.", "/"); 
            	//maven工程存放路径
            	String path = System.getProperty("user.dir") + "/src/main/java/" + packagePath.replaceAll("\\.", "/");
                File file = new File(path);
                if(!file.exists()){
                	file.mkdirs();
                }
                String resPath = path+"/"+initcap(tableName) + ".java";
                System.out.println("resPath=" + resPath);
                FileUtils.writeStringToFile(new File(resPath), content);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} 
    }
     
    /**
     * 获取指定数据库和用户的所有表名
     * @param conn 连接数据库对象
     * @param user 用户
     * @param database 数据库名
     * @return
     */
    public static List<String> getAllTableNames() {
    	try {
			Connection conn = DriverManager.getConnection(MYSQLURL,NAME,PASSWORD);
			List<String> tableNames = new ArrayList();
			DatabaseMetaData dbmd = conn.getMetaData();
		    // 表名列表
		    ResultSet resultSet = dbmd.getTables(DATASOURCE, null, null, new String[] { "TABLE" });
		    // 输出 table_name
		    while(resultSet.next()){
		    	tableNames.add(resultSet.getString("TABLE_NAME"));
            }
            resultSet.close();
		    return tableNames;	
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;				    
    }
    
    /**
    * 解析处理(生成实体类主体代码)
    */
    private static String parse(String[] colNames, String[] colTypes, int[] colSizes, String packagePath, String tableName,String memo) {
        StringBuffer sb = new StringBuffer();
        sb.append("package " + packagePath + ";\r\n\r\n");
        if (f_util) {
            sb.append("import java.util.Date;\r\n");
        }
        if (f_sql) {
            sb.append("import java.sql.*;\r\n\r\n\r\n");
        }
        if (f_ser) {
        	sb.append("import java.io.Serializable;\r\n\r\n\r\n");
		}
        if (memo==null||memo.length()==0) {
			memo="实体类";
		}
        sb.append("/**\r\n" + 
        		" * "+memo+"\r\n" + 
        		" * @author XJY\r\n" + 
        		" */\r\n");
        sb.append("public class " + initcap(tableName) + " implements Serializable {\r\n\r\n");
        processAllAttrs(sb);
        sb.append("\r\n");
        processAllstructureMethod1(initcap(tableName),sb);
        sb.append("\r\n");
        processAllstructureMethod2(initcap(tableName),sb);
        sb.append("\r\n");
        processAllMethod(sb);
        sb.append("}\r\n");
        System.out.println(sb.toString());
        return sb.toString();
    }
    
    /**
     * 生成构造方法
     * @param tableName  类名
     * @param sb   
     */
    private static void processAllstructureMethod1(String tableName,StringBuffer sb) {
    	sb.append("    public "+tableName+"(){\n\n    }\n\n");
    	StringBuffer sBuffer1=new StringBuffer();
    	StringBuffer sBuffer2=new StringBuffer();    	
    	for (int i = 0; i <= 3; i++) {
    		sBuffer1.append(sqlType2JavaType(colTypes[i]) + " " + colnames[i] + ",");
        }
    	sBuffer1.deleteCharAt(sBuffer1.length()-1);
    	for (int i = 0; i <= 3; i++) {
    		sBuffer2.append("       this." + colnames[i] + "="+colnames[i]+";\n");
        }
    	
    	String content="    public "+tableName+"("+sBuffer1+") {\n"+sBuffer2+"    }\n\n";
    	sb.append(content);
    }
    
    private static void processAllstructureMethod2(String tableName,StringBuffer sb) {
    	StringBuffer sBuffer3=new StringBuffer();
    	StringBuffer sBuffer4=new StringBuffer();    	
    	for (int i = 0; i <=colnames.length-1; i++) {
    		sBuffer3.append(sqlType2JavaType(colTypes[i]) + " " + colnames[i] + ",");
        }
    	sBuffer3.deleteCharAt(sBuffer3.length()-1);
    	for (int i = 0; i <= colnames.length-1; i++) {
    		sBuffer4.append("       this." + colnames[i] + "="+colnames[i]+";\n");
        }
    	
    	String content="    public "+tableName+"("+sBuffer3+") {\n"+sBuffer4+"    }\n\n";
    	sb.append(content);
    }
    
    /**
    * 生成所有的方法
    * 
    * @param sb
    */
    private static void processAllMethod(StringBuffer sb) {
        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tpublic void set" + initcap(colnames[i]) + "("
                    + sqlType2JavaType(colTypes[i]) + " " + colnames[i]
                    + "){\r\n");
            sb.append("\t\tthis." + colnames[i] + "=" + colnames[i] + ";\r\n");
            sb.append("\t}\r\n\r\n");
            sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get"
                    + initcap(colnames[i]) + "(){\r\n");
            sb.append("\t\treturn " + colnames[i] + ";\r\n");
            sb.append("\t}\r\n\r\n");
        }
    }
    /**
    * 解析输出属性
    * 
    * @return
    */
    private static void processAllAttrs(StringBuffer sb) {   	
        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + colnames[i] + ";\t\t\t\t\t\t\t//"+colcomment[i]+"\n");
        }
    }
    /**
    * 把输入字符串的首字母改成大写
    * 
    * @param str
    * @return
    */
    private static String initcap(String str) {
        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0]-32);
        }
        return getCamelStr(new String(ch));
    }
    
    //例：user_name --> userName
    private static String getCamelStr(String s){
    	while(s.indexOf("_")>0){
			int index = s.indexOf("_");
			//System.out.println(s.substring(index+1, index+2).toUpperCase());
			s = s.substring(0, index) + s.substring(index+1, index+2).toUpperCase() + s.substring(index+2);
		}
		return s;
    }
 
    private static String sqlType2JavaType(String sqlType) {
        if (sqlType.equalsIgnoreCase("bit")) {
            return "bool";
        } else if (sqlType.equalsIgnoreCase("tinyint")) {
            return "byte";
        } else if (sqlType.equalsIgnoreCase("smallint")) {
            return "short";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("integer")) {
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "Float";
        } else if (sqlType.equalsIgnoreCase("numeric")
                || sqlType.equalsIgnoreCase("real")
                || sqlType.equalsIgnoreCase("double")
                || sqlType.equalsIgnoreCase("decimal")) {
            return "Double";           
        } else if (sqlType.equalsIgnoreCase("money")
                || sqlType.equalsIgnoreCase("smallmoney")) {
            return "Double";
        } else if (sqlType.equalsIgnoreCase("varchar")
                || sqlType.equalsIgnoreCase("char")
                || sqlType.equalsIgnoreCase("nvarchar")
                || sqlType.equalsIgnoreCase("nchar")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime")||sqlType.equalsIgnoreCase("date")) {
            return "Date";
        }
 
        else if (sqlType.equalsIgnoreCase("image")) {
            return "Blob";
        } else if (sqlType.equalsIgnoreCase("text")) {
            return "Clob";
        }
        return null;
    }
    
    /** 
     * 获得某表中所有字段的注释 
     * @param tableName 
     * @return 
     * @throws Exception 
     */  
    public static String[] getColumnCommentByTableName(String tableName) throws Exception {     
    	String comment=null;
        Connection conn = DriverManager.getConnection(MYSQLURL,NAME,PASSWORD);  
        Statement stmt = conn.createStatement();  
        ResultSet rs = stmt.executeQuery("show full columns from " + tableName);
        while (rs.next()) {
    		comment+= rs.getString("Comment")+",";   		
		}
        String result=comment.substring(4, comment.length()-1);
        String[] strArray=result.split(",");
		return strArray;
    } 
    
	

}
